package com.cskaoyan.com.stack;

import java.util.Objects;

/**
 *  使用数组实现一个数据结构表现为栈的数据容器
 */
public class MyArrayStack <T> {

    private static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
    private static final int INIT_CAPACITY = 10;
    private Object[] objs; // 底层数组
    private int size; // 存储的元素数目

    // 构造方法
    public MyArrayStack(){
        this.objs = new Object[INIT_CAPACITY];
    }
    public MyArrayStack(int initCapacity){
        if (initCapacity < 1 || initCapacity > MAX_CAPACITY){
            throw new IllegalArgumentException("initCapacity = "+initCapacity);
        }
        this.objs = new Object[initCapacity];
    }

    // push, pop, peek

    /**
     * 栈的入栈操作
     * @param value: 要入栈的内容
     * @return: 入栈是否成功
     */
    public boolean push(T value){
        // 数组是否满了, 扩容
        if (size == objs.length){
            int newLen = getLen();
            grow(newLen);
        }
        // 走到这, 一定意味着, 数组中有空间存储数据
        objs[size] = value;
        size++;
        return true;
    }
    private void grow(int newLen) {
        Object[] newObjs = new Object[newLen];

        for (int i = 0; i < objs.length; i++) {
            newObjs[i] = objs[i];
        }

        objs = newObjs;
    }
    private int getLen() {
        int oldLen = objs.length;
        int newLen = oldLen << 1;

        if (newLen < 0 || newLen > MAX_CAPACITY){
            newLen = MAX_CAPACITY;
        }

        if (oldLen == newLen){
            throw new RuntimeException("stack is full");
        }

        return newLen;
    }

    /**
     * 栈的出栈操作
     * @return;被出栈的栈顶数据
     */
    public T pop(){
        if (isEmpty()){
            throw new RuntimeException("stack is empty");
        }
        // 栈不空
        T oldValue = (T) objs[size-1];
        // objs[size-1] = null;
        size--;

        return oldValue;
    }

    /**
     * 查看栈的栈顶数据
     * @return: 栈顶栈顶数据
     */
    public T peek(){
        if (isEmpty()){
            throw new RuntimeException("stack is empty");
        }

        return (T)objs[size-1];
    }


    public boolean isEmpty(){
        return size == 0;
    }
}
